﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace myLittleC
{
    /// <summary>
    /// представление унарной операции
    /// </summary>
    class SynataxUnaryOp :ISyntaxExpression  
    {
        public ISyntaxExpression Argument { get; private set; }         
        public bool Postfix  { get; private set; }         
        public SubTokenType Operation { get; private set; }

        public SynataxUnaryOp(SubTokenType iOper, ISyntaxExpression iArgument) : this(iOper, iArgument, false) { }
        public SynataxUnaryOp(SubTokenType iOper, ISyntaxExpression iArgument, bool iPostfix)           
        {
            Operation = iOper;
            //if (!(arg is IPartOfExpession || arg is IExpression)) ну тут будет эксепшен
            Argument = iArgument;
            Postfix = iPostfix;
        }

        public override String ToString()
        {
            return Postfix ? String.Format(" {1} {0}", Argument.ToString("  "), Tokenizer.StringOperation(Operation))
                   : String.Format("{0}  {1}", Argument.ToString(" "), Tokenizer.StringOperation(Operation)); 
        }

        public virtual String ToString(String Shift)
        {
            return Postfix ? String.Format("{1}{2}\n{0}", Argument.ToString(Shift), Shift, Tokenizer.StringOperation(Operation))
                : String.Format("{0}\n{1}{2}", Argument.ToString(Shift + " "), Shift, Tokenizer.StringOperation(Operation)); 
        }
        public virtual String ToString(String prev, bool up)
        {
            String PrevLeft = (prev == "") ?  "  " : String.Format("{0}{1}     ", prev, (up ? " " : "│"));
            String PrevCenter = (prev == "") ? " " : String.Format("{0}{1}────", prev, (up ? "┌" : "└"));

            String Left = Postfix ? String.Format("{0}┌────[{1}]", PrevLeft, Tokenizer.StringOperation(Operation)) : Argument.ToString(PrevLeft, true);
            String ce = Postfix ? Argument.ToString(prev, up) : String.Format("{0}[{1}]", PrevCenter, Tokenizer.StringOperation(Operation));
            return String.Format("{0}\n{1}│\n{2}", Left, PrevLeft, ce);
        }
        
    }
    /// <summary>
    /// представление бинарной операции
    /// </summary>
    class SyntaxBinaryOp : ISyntaxExpression
    {
        public ISyntaxExpression Left { get; private set; }
        public ISyntaxExpression Right { get; private set; }
        public bool IsLeft { get; private set; }

        public SubTokenType Operation { get; private set; }

        public SyntaxBinaryOp(SubTokenType iOper, ISyntaxExpression iLeft, ISyntaxExpression iRight)           
        {
            Operation = iOper;
            Left = iLeft;
            Right = iRight;
        }

        public override String ToString()
        { return String.Format("{0} {1} {2}", Left.ToString(" "), Tokenizer.StringOperation(Operation), Right.ToString(" ")); }
        public String ToString(String Shift)
        { return String.Format("{0}\n{1}{2}\n{3}", Left.ToString(Shift + " "), Shift, Tokenizer.StringOperation(Operation), Right.ToString(Shift + " ")); }

        public String ToString(String prev, bool up)
        {
            String PrevLeft, PrevRight, PrevCenter;
            if (prev == "")
            {
                PrevCenter = " ";
                PrevRight = PrevLeft = "  ";
            }
            else
            {
                PrevLeft = String.Format("{0}{1}     ", prev, (up ? " " : "│"));
                PrevRight = String.Format("{0}{1}     ", prev, (up ? "│" : " "));
                PrevCenter = String.Format("{0}{1}────", prev, (up ? "┌" : "└"));
            }

            String SLeft = Left.ToString(PrevLeft, true);
            String SCenter = String.Format("{0}[{1}]", PrevCenter, Tokenizer.StringOperation(Operation));
            String SRight = Right.ToString(PrevRight, false);

            return String.Format("{0}\n{1}│\n{2}\n{3}│\n{4}", SLeft, PrevLeft, SCenter, PrevRight, SRight);
        }
    }

    /// <summary>
    /// реализация целочисленныйх коснстат
    /// </summary>
    class SyntaxConstInt : ISyntaxConst
    {
        public SubTokenType Type {get;  private set;}
        public Int32 Value {get;  private set;}

        /// <summary>
        /// возращает значение в типе обчекст, для обжности интерфейса
        /// </summary>
        public Object obValue { get {return (Object) Value;}}

        public ExpType ExType { get; private set; }

        public SyntaxConstInt (Token iToken) { Type = iToken.SubType; Value = (Int32) iToken.Value; }
	    
        public override String ToString() { return " "  + Value;}
        public String ToString(String Shift) { return Shift + Value;}

        public String ToString(String prev, bool up)
        { return String.Format("{0}|{1}|", ((prev == "") ? " " : String.Format("{0}{1}────", prev, (up ? "┌" : "└"))), Value);}
    }
    /// <summary>
    /// 
    /// </summary>
    class SyntaxConstReal : ISyntaxConst
    {
        public SubTokenType Type {get;  private set;}
        public float Value {get;  private set;}
        public Object obValue { get { return (Object)Value; } }
        
        public ExpType ExType { get; private set; }

        public SyntaxConstReal (Token iToken) { Type = iToken.SubType; Value = (float) iToken.Value; }
	    
        public override String ToString() { return " "  + Value;}
        public String ToString(String Shift) { return Shift + Value;}

        public String ToString(String prev, bool up)
        { return String.Format("{0}|{1}|", ((prev == "") ? " " : String.Format("{0}{1}────", prev, (up ? "┌" : "└"))), Value);}
    }

    /// <summary>
    /// реализация идентефикатора
    /// </summary>
    class SyntaxIdentefier : ISyntaxExpression
    {
        public String Name {get ; private set;}
        
        
        public SyntaxIdentefier(String iName) { Name = iName;}

        public override String ToString() { return " " + Name.ToString();}
        public String ToString(String Shift) { return Shift + Name.ToString();}

        public String ToString(String prev, bool up)
        { return String.Format("{0}|{1}|", ((prev == "") ? " " : String.Format("{0}{1}────", prev, (up ? "┌" : "└"))), Name); }
    };

    /// <summary>
    /// класс реализующий блок
    /// </summary>
    class SyntaxBlok : ISyntaxStat
    { 
        public SyntaxBlok() :this(null){}
        public SyntaxBlok(SyntaxBlok iParrent) 
        {
            Table = new SymbolTable();
            Parrent = iParrent;
        }
       
        public void Add(ISyntaxNode iS) {SyntaxNodes.Add(iS); }
        public void Add(ISymbol iS) {Table.Add(iS); }

        public void EndDefentions() { StartExp = true; }
        public bool HaveNodes { get { return SyntaxNodes.Count != 0; } }

        public ISymbol Find(String iName) { return Table.Find(iName); }
        public ISymbol FindType(String iName) { return Table.FindType(iName); }

        public ISymbol FindWithParent(String iName) {  return Find(iName) ?? (Parrent != null ? Parrent.FindTypeWithParent(iName) : null); }
        public ISymbol FindTypeWithParent(String iName) {  return Table.FindType(iName) ?? (Parrent != null ? Parrent.FindTypeWithParent(iName) : null); }

        public bool HaveFunk(String iName) {   return Table.FindFunk(iName) != null;}

        public String ToString(String Shift) { return WriteTable("", ""); }
        public String ToString(String prev, bool up) { return " "; }

        public override  String ToString() { return WriteTable("", ""); }
		
		
		public String ToString(String Shift, String Name) { return WriteTable(Shift, Name); }
        public String WriteTable(String Shift, String Name)
        {
			return String.Format("\n{3}{0}:\n{1}\n{2}\n{3}END BLOK\n",
			                       (Name != "" ? Name : "New Blok"),
			                      Table.ToString(Shift),  writeTable(Shift + Symbol.oneShift), Shift); 
		}

        private String writeTable(String Shift)
        {
            String res = "";
            foreach (ISyntaxNode Node in SyntaxNodes)
                if (Node is SyntaxBlok)
                    res += ((SyntaxBlok)Node).WriteTable(Shift, "");
            return res;
        }

        //Propertis
        public bool MayDefs { get { return !StartExp; } }
        public bool MayExp { get { return StartExp; } }

        public SyntaxBlok Parrent { get; private set; }
        public SymbolTable Table { get; private set; }

        //private data
       	bool StartExp = false;
       	private List<ISyntaxNode> SyntaxNodes = new List<ISyntaxNode>();
    }
    /*
    class SyntaxVar : ISyntaxExpression
    {
        public String Name { get; private set; }
        public ExpType ExType { get; private set; }

        public SyntaxVar(String iName, ExpType iType) { Name = iName; ExType = iType; }
        public SyntaxVar(String iName) { Name = iName; }

        public override String ToString() { return " " + Name.ToString(); }
        public String ToString(String Shift) { return Shift + Name.ToString(); }

        public String ToString(String prev, bool up)
        { return String.Format("{0}|{1}|", ((prev == "") ? " " : String.Format("{0}{1}────", prev, (up ? "┌" : "└"))), Name); }
    };
     */
}

